/*
 * llc_state_machine.c
 *
 *  Created on: Apr 20, 2013
 *      Author: ILYA
 */
#include "llc_create_frame.h"
#include "CRTP_ARP_table.h"

/*the port_pid parameter is Protocol Identifier(PID) this is same as port in application layer,
 * the *data field, is that data, which you want to transfer*/
int create_frame(struct pbuf *frame, char poll_bit, int type, int port_pid, data_type *data)
{
	if(poll_bit)
		*llc_mac_if->llc_ptr_mac.controlField = type | POLL_FINAL_BIT_MASK;
	else
		*llc_mac_if->llc_ptr_mac.controlField = type;

	switch(type)
	{
	case UN_SIM: //base
	{
		struct SIM_RIMFrame *simFrame = frame->payload;
		simFrame->byte3.Probability = llc_sim_rim_init.llc_sim_probability;
		simFrame->byte3.RIM = RIM_MAX_COUNT-1;

		int i;
		for(i = 0; i < RIM_MAX_COUNT; i++)
			listOfRIMFrames[i]->isNULL = 1;

		simFrame->byte4.bit6 = 0;
		simFrame->byte4.bit7 = 0;
		simFrame->byte4.Priority = llc_sim_rim_init.llc_sim_rim_priority;
		simFrame->byte4.TxLoad = state_of_tx_buffer;
		simFrame->waitingTime = llc_sim_rim_init.llc_sim_waiting_time;
		simFrame->reserved = 0x00;
		simFrame->TSN_7_12 = uniqueSerialNumber;
		simFrame->reserved_byte13 = 0x00;
	}
	break;
	case UN_XID_CMD: //base
	{
		struct XID_Frame *xidFrame = frame->payload;

		int i;
		xidFrame->link_id = 255;
		for(i = 0; i < MAX_LINK_ID; ++i)
		{
			if((is_arp_i_not_null[i/8] & (128 >> (i%8))) == 0)
			{
				xidFrame->link_id = i;
				break;
			}
		}
		if(i == MAX_LINK_ID)
		{
			delete_from_arp(queueing_row);
			xidFrame->link_id = queueing_row;
			queueing_row += 1;
			if(queueing_row >= MAX_LINK_ID)
				queueing_row = 0;
		}
#ifdef DEBUG_LLC
		printk("linkid = %d\r\n", xidFrame->link_id); //iiiiiiiiiiiiiiiiiiiiiiiiiiiii
#endif /*DEBUG_LLC*/

		xidFrame->rsl = *RSL;
		xidFrame->snr = *SNR;
		xidFrame->rf_pwr = *RF_PWR;
		xidFrame->RSN_7_12 = listOfRIMFrames[current_rim - 1]->RIMFrame.TSN_7_12;
		xidFrame->reserved_byte13 = 0x00;

		//xidFrame->information_field = ((unsigned char *)&RSN_7_12) + 1;
	}
	break;

///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////

	case UN_RIM: //remote
	{
		struct SIM_RIMFrame *rimFrame = frame->payload;
		rimFrame->byte3.Probability = llc_sim_rim_init.llc_sim_probability;
		srand(TC1_Get_us()); unsigned int x_rand = RIM_MAX_COUNT-1;
		rimFrame->byte3.RIM = rand() % x_rand;

		listOfRIMFrames[0]->isNULL = 1;

		rimFrame->byte4.bit6 = 0;
		rimFrame->byte4.bit7 = 0;
		rimFrame->byte4.Priority = llc_sim_rim_init.llc_sim_rim_priority;
		rimFrame->byte4.TxLoad = state_of_tx_buffer;
		rimFrame->waitingTime = llc_sim_rim_init.llc_sim_waiting_time;
		rimFrame->reserved = 0x00;
		rimFrame->TSN_7_12 = uniqueSerialNumber;
		rimFrame->reserved_byte13 = 0x00;
	}
	break;
	case UN_XID_RESP: //remote
	{
		struct XID_Frame *xidFrame = frame->payload;
		xidFrame->link_id = listOfRIMFrames[0]->Link_ID;
		xidFrame->rsl = *RSL;
		xidFrame->snr = *SNR;
		xidFrame->rf_pwr = *RF_PWR;
		xidFrame->RSN_7_12 = uniqueSerialNumber;
		xidFrame->reserved_byte13 = 0x00;

		//xidFrame->information_field = ((unsigned char *)&RSN_7_12) + 1;
	}
	break;


//////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////

	case UN_UI_CMD: //base
	case UN_UI_RESP: //remote
	{
		if(type == UN_UI_RESP && data->LinkID != listOfRIMFrames[0]->Link_ID)
		{
#ifdef DEBUG_LLC
			printk("\r\nError :  The remote Link Id is incorrect. See llc_create_frame.c->case UN_UI_RESP:\r\n");
#endif /*DEBUG_LLC*/
			return LINK_ID_ERROR;
		}
		struct UI_Frame *uiFrame = frame->payload;
		uiFrame->link_id = data->LinkID;
		uiFrame->pid = port_pid;
		if(data->size > sizeof(uiFrame->firstInformationField))
		{
			memcpy(uiFrame->firstInformationField, data->data, sizeof(uiFrame->firstInformationField));
			unsigned char *__secondInformationField = ((unsigned char *)uiFrame->firstInformationField) +
					sizeof(uiFrame->firstInformationField) + sizeof(uiFrame->crc8);
			unsigned short *__fcs = (unsigned short *)(uiFrame->firstInformationField + data->size + sizeof(uiFrame->crc8));
			memcpy(__secondInformationField, data->data + sizeof(uiFrame->firstInformationField),
					data->size - sizeof(uiFrame->firstInformationField));
			unsigned short fcs_variable = Crc16ByTable(__secondInformationField, data->size - sizeof(uiFrame->firstInformationField));
			memcpy(__fcs, &fcs_variable, sizeof(unsigned short));
		}
		else
		{
			memset(uiFrame->firstInformationField, 0, sizeof(uiFrame->firstInformationField));
			memcpy(uiFrame->firstInformationField, data->data, data->size);
		}
	}
	break;
	}
	return NO_ERRORS;
}
